# -*- coding: UTF-8 -*-
import json

from sqlalchemy import ForeignKey
from sqlalchemy.orm import relationship, backref
from sqlalchemy_utils import ChoiceType

from app.settings import local_time, join_path, LOG_DIR
from . import Base, Column, Integer, String, DateTime, Boolean
from .model_mixin import ModelMixin
from .work_status import UserAction, TaskStatus


class User(Base, ModelMixin):
    __tablename__ = 'user'

    uid = Column(Integer, nullable=False, primary_key=True)
    account = Column(String(14), unique=True, nullable=False)
    name = Column(String(14), nullable=False, unique=True)
    password = Column(String(128), nullable=False)

    enabled = Column(Boolean, default=True)
    create_date = Column(DateTime, nullable=False, default=local_time)
    update_date = Column(DateTime, nullable=False, default=local_time, onupdate=local_time)

    def is_admin(self) -> bool:
        return RoleMap.query.filter_by(uid=self.uid, rid=1, enabled=True).count() > 0

class Role(Base, ModelMixin):
    __tablename__ = 'role'

    rid = Column(Integer, primary_key=True, autoincrement=True)
    name = Column(String(14), nullable=False, default='Unname')

    enabled = Column(Boolean, default=True)
    create_date = Column(DateTime, nullable=False, default=local_time)
    update_date = Column(DateTime, nullable=False, default=local_time, onupdate=local_time)


class RoleMap(Base, ModelMixin):
    __tablename__ = 'role_map'
    id = Column(Integer, primary_key=True, autoincrement=True)
    rid = Column(Integer, ForeignKey('role.rid'))
    uid = Column(Integer, ForeignKey('user.uid'))

    enabled = Column(Boolean, default=True)
    create_date = Column(DateTime, nullable=False, default=local_time)
    update_date = Column(DateTime, nullable=False, default=local_time, onupdate=local_time)
    user = relationship('User', backref=backref('role_maps'), uselist=False, foreign_keys=[uid])
    role = relationship('Role', backref=backref('role_maps'), uselist=False, foreign_keys=[rid])


class Task(Base, ModelMixin):
    __tablename__ = 'task'
    tid = Column(Integer, primary_key=True, autoincrement=True, comment='任务号')
    uid = Column(Integer, ForeignKey('user.uid'), default=0, comment='创建人id')
    fid = Column(Integer, ForeignKey('workflow.fid'), default=0, nullable=False)
    status = Column(Integer, default=TaskStatus.init, nullable=False)
    # status = Column(ChoiceType(TaskStatus.get_choices(), impl=Integer()), default=TaskStatus.init, nullable=False)

    level = Column(Integer, default=0, nullable=False)
    create_date = Column(DateTime, nullable=False, default=local_time)
    update_date = Column(DateTime, nullable=False, default=local_time, onupdate=local_time)
    complete_date = Column(DateTime, nullable=False, default=local_time, onupdate=local_time)
    user = relationship('User', backref=backref('task_list'), uselist=False, foreign_keys=[uid])
    flow = relationship('WorkFlow', backref=backref('task_list'), uselist=False, foreign_keys=[fid])

class TaskLog(Base, ModelMixin):
    __tablename__ = 'task_log'
    id = Column(Integer, primary_key=True, autoincrement=True)
    tid = Column(Integer, ForeignKey('task.tid'), nullable=False)
    fid = Column(Integer, ForeignKey('workflow.fid'), default=0, nullable=True)
    create_date = Column(DateTime, nullable=True, default=local_time)
    directory = Column(String(14), nullable=True, default='')

    task = relationship('Task', backref=backref('task_log'), uselist=False, foreign_keys=[tid])
    flow = relationship('WorkFlow', backref=backref('task_log'), uselist=False, foreign_keys=[fid])

    def abs_path(self):
        return join_path(LOG_DIR, str(self.tid)+'@'+self.create_date.strftime('%Y-%m-%d %H-%M-%S') + '.json')

    def get_data(self):
        with open(self.abs_path(), 'r') as f:
            # from collections import OrderedDict
            data = json.load(f)

        return data


import enum


class UserType(enum.Enum):
    init=0
    passed=2
    rejected=4
    returned=16
    saved= 1
    stoped= 8
    voided=32

class Process(Base, ModelMixin):
    __tablename__ = 'process'
    id = Column(Integer, primary_key=True, autoincrement=True)
    pid = Column(Integer, default=0)
    ppid = Column(Integer, default=0, comment='parent pid')
    tid = Column(Integer, ForeignKey('task.tid'))
    nid = Column(Integer, ForeignKey('node.nid'))
    uid = Column(Integer, ForeignKey('user.uid'))
    rid = Column(Integer, ForeignKey('role.rid'))
    fid = Column(Integer, ForeignKey('workflow.fid'))

    action = Column( Integer() , default = UserAction.init, comment='user action result',nullable=False)
    # status = Column(Integer() , default=ProcessStatus.init, comment='flow status',nullable=False)
    status = Column(ChoiceType(TaskStatus.get_choices(), impl=Integer()), default=TaskStatus.init, nullable=False)

    active = Column(Boolean, default=True, comment='erp active')
    level = Column(Integer, default=0, comment='处理优先级')
    create_date = Column(DateTime, nullable=False, default=local_time)
    update_date = Column(DateTime, nullable=False, default=local_time, onupdate=local_time)

    task = relationship('Task', backref=backref('process_list'), uselist=False, foreign_keys=[tid])
    node = relationship('Node', backref=backref('process_list'), uselist=False, foreign_keys=[nid])
    user = relationship('User', backref=backref('process_list'), uselist=False, foreign_keys=[uid])
    role = relationship('Role', backref=backref('process_list'), uselist=False, foreign_keys=[rid])
    flow = relationship('WorkFlow', backref=backref('process_list'), uselist=False, foreign_keys=[fid])


class WorkFlow(Base, ModelMixin):
    __tablename__ = 'workflow'
    fid = Column(Integer, primary_key=True, )
    name = Column(String(255))
    category = Column(String(32))
    work_tables = Column(String(255))
    doc = Column(String(255), default='', nullable=False)
    enabled = Column(Boolean, default=True)
    create_date = Column(DateTime, default=local_time)


class Node(Base, ModelMixin):
    __tablename__ = 'node'
    nid = Column(Integer, primary_key=True, nullable=False)
    fid = Column(Integer, ForeignKey('workflow.fid'))
    name = Column(String(255), default='', nullable=False)
    doc = Column(String(255), default='', nullable=False)
    node_type = Column(String(255), default='', comment='base class name')
    form_path = Column(String(255), default='', nullable=False)
    form_class_name = Column(String(255), default='', nullable=False)
    has_user = Column(Boolean, default=False)
    has_role = Column(Boolean, default=False)
    has_submit = Column(Boolean, default=False)
    has_save = Column(Boolean, default=False)
    has_pass = Column(Boolean, default=True)
    has_reject = Column(Boolean, default=False)
    has_return = Column(Boolean, default=False)
    has_void = Column(Boolean, default=False)
    enabled = Column(Boolean, default=True)
    create_date = Column(DateTime, default=local_time)
    flow = relationship('WorkFlow', backref=backref('nodes'), uselist=False, foreign_keys=[fid])


class NodeConfig(Base, ModelMixin):
    __tablename__ = 'node_config'
    id = Column(Integer, primary_key=True, autoincrement=True)
    nid = Column(Integer, ForeignKey('node.nid'))
    uid = Column(Integer, ForeignKey('user.uid'), default=0)
    rid = Column(Integer, ForeignKey('role.rid'), default=0)
    fid = Column(Integer)
    enabled = Column(Boolean, default=True)

    create_uid = Column(Integer, ForeignKey('user.uid'), default=0)
    create_date = Column(DateTime, default=local_time)
    node = relationship('Node', backref=backref('configs'), uselist=False, foreign_keys=[nid])
    user = relationship('User', backref=backref('node_configs'), uselist=False, foreign_keys=[uid])
    role = relationship('Role', backref=backref('node_configs'), uselist=False, foreign_keys=[rid])
    create_user = relationship('User', backref=backref('create_node_configs'), uselist=False, foreign_keys=[create_uid])


class Edge(Base, ModelMixin):
    __tablename__ = 'edge'
    id = Column(Integer, primary_key=True, autoincrement=True)
    parent_id = Column(Integer, ForeignKey('node.nid'))
    child_id = Column(Integer, ForeignKey('node.nid'))
    fid = Column(Integer)
    name = Column(String(255), default='', nullable=False)
    doc = Column(String(255), default='', nullable=False)
    enabled = Column(Boolean, default=True)
    create_uid = Column(Integer, ForeignKey('user.uid'))
    create_date = Column(DateTime, default=local_time)
    parent = relationship('Node', backref=backref('out_edges'), uselist=False, foreign_keys=[parent_id])
    child = relationship('Node', backref=backref('in_edges'), uselist=False, foreign_keys=[child_id])
    create_user = relationship('User', backref=backref('create_edges'), uselist=False, foreign_keys=[create_uid])

# class EdgeRule(Base, ModelMixin):
#     __tablename__ = 'edge_rule'
#     id = Column(Integer, primary_key=True, autoincrement=True)
#     edge_id = Column(Integer, ForeignKey('edge.id'))
#     target = Column(String(255), default='User', nullable=False)
#     operator = Column(String(3), default='AND', nullable=False)
#     group = Column(String(3), default='', nullable=False)
#
#     edge = relationship('Edge', backref=backref('rules'), uselist=False, foreign_keys=[edge_id])
